#!/usr/bin/env python
# -*- coding:utf-8 -*-

import ctypes
from dapi import wintype
import pefile
from capstone import *
from lib import settings
from lib.utils import loader
import os
from lib.utils import printer
import struct
class debugger():

    def __init__(self,hmodule:dict):
        self.debugger_active = None
        self.pid = None
        self.h_process = None
        self.h_thread = None
        self.context = None
        self.breakpoints = {}
        self.first_breakpoints = True
        self.exception = None
        self.exception_address = None
        self.ep_address = None
        self.process_information = wintype.PROCESS_INFORMATION()
        self.hmodule = hmodule
        self.debug_programe = ""
        #0523
        self.peb = None
        self.tebs = {}
    
    def load_64_exe(self,path_to_exe,bAddr=None):
        creation_flags = wintype.DEBUG_PROCESS
        startupinfo = wintype.STARTUPINFO()
        tbi = wintype.THREAD_BASIC_INFORMATION()
        if bAddr == None:
            self.set_ep_address(path_to_exe)
        else:
            self.ep_address = int(bAddr,16)
        self.debug_programe = path_to_exe.split("\\")[-1]
        startupinfo.dwFlags = 0x01
        startupinfo.wShowWindow = 0x0
        startupinfo.cb = ctypes.sizeof(startupinfo)

        if ctypes.windll.kernel32.CreateProcessW(
            path_to_exe,
            None,
            None,
            None,
            None,
            creation_flags,
            None,
            None,
            ctypes.byref(startupinfo),
            ctypes.byref(self.process_information)):
            printer.info("成功加载程序!")
            printer.info("程序进程ID[PID]: %d" % self.process_information.dwProcessId)
            self.pid = self.process_information.dwProcessId
            self.h_process = self.open_process(self.process_information.dwProcessId)
            if self.ep_address:
                bp = self.set_software_breakpoint(self.ep_address)
                if bp:
                    printer.info("断点: 0x%08x" % self.ep_address)
                else:
                    printer.warn("断点设置错误!")
            
            self.debugger_active = True
            #0523
            selector_entry = wintype.LDT_ENTRY()#LDT
            thread_context = self.get_thread_context_debug(h_thread=self.process_information.hThread)
            segFs = 0x50
            if ctypes.windll.kernel32.Wow64GetThreadSelectorEntry(self.process_information.hThread, segFs, ctypes.byref(selector_entry)):
                teb = selector_entry.BaseLow
                teb += (selector_entry.HighWord.Bits.BaseMid << 16) + (selector_entry.HighWord.Bits.BaseHi << 24)
                self.tebs[self.process_information.dwThreadId] = teb
                self.peb = self.read_process_memory(teb + 0x30, 4)
                self.peb = struct.unpack("<L", self.peb)[0]
                #for mod in self.interate_modules():
                    #print(hex(mod.modBaseAddr))
        else:
            printer.warn("load_64_exe错误: 0x%08x." % ctypes.windll.kernel32.GetLastError())
    def open_process(self,pid):
        hprocess = ctypes.windll.kernel32.OpenProcess(wintype.PROCESS_ALL_ACCESS,False,pid)
        return hprocess
    def open_thread64(self,tid):
        h_thread = ctypes.windll.kernel32.OpenThread(wintype.THREAD_ALL_ACCESS64,0,tid)
        if h_thread is not None:
            return h_thread
        else:
            printer.warn("未成功获取当前线程句柄!")
            return False
    def get_thread_context64(self,tid=None,h_thread=None):
        context = wintype.CONTEXT64()
        context.ContextFlags = wintype.CONTEXT_FULL_64
        if h_thread == None:
            self.h_thread = self.open_thread64(tid)
        ctypes.windll.kernel32.SuspendThread(self.h_thread)
        gtc = ctypes.windll.kernel32.GetThreadContext
        gtc.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
        gtc.restypes = ctypes.c_uint
        if gtc(self.h_thread,ctypes.byref(context)):
            ctypes.windll.kernel32.ResumeThread(self.h_thread)
            return context
        else:
            ctypes.windll.kernel32.ResumeThread(self.h_thread)
            printer.warn("get_thread_context64错误: %d" % ctypes.windll.kernel32.GetLastError())
            return False
    #0528
    def get_thread_context_debug(self,h_thread):
        context = wintype.CONTEXT64()
        context.ContextFlags  = wintype.CONTEXT_FULL_64 | wintype.CONTEXT_DEBUG_REGISTERS_64
        gtc = ctypes.windll.kernel32.GetThreadContext
        gtc.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
        gtc.restypes = ctypes.c_uint
        if not gtc(h_thread,ctypes.byref(context)):
            printer.warn("get_thread_context64错误: %d" % ctypes.windll.kernel32.GetLastError())
            return False
        if not h_thread:
            ctypes.windll.kernel32.CloseHandle(h_thread)
        return context

    def enumerate_threads(self):
        thread_entry = wintype.THREADENTRY32()
        thread_list = []
        snapshot = ctypes.windll.kernel32.CreateToolhelp32Snapshot(
           wintype.TH32CS_SNAPPROCESS | wintype.TH32CS_SNAPTHREAD,0
        )
        if snapshot is not None:
            thread_entry.dwSize = ctypes.sizeof(thread_entry)
            success = ctypes.windll.kernel32.Thread32First(snapshot, ctypes.byref(thread_entry))
            while success:
                if thread_entry.th32OwnerProcessID == self.pid:
                    thread_list.append(thread_entry.th32ThreadID)
                success = ctypes.windll.kernel32.Thread32Next(snapshot, ctypes.byref(thread_entry))
            ctypes.windll.kernel32.CloseHandle(snapshot)
            return thread_list
        else:
            return False
    def general_register_info64(self,ctx):
        printer.info("寄存器信息:")
        space = "   "
        aInfo = "Rax: 0x%016x" % ctx.Rax
        aInfo += space + "Rcx: 0x%016x" % ctx.Rcx
        aInfo += space + "Rdx: 0x%016x" % ctx.Rdx
        bInfo = "Rbx: 0x%016x" % ctx.Rbx
        bInfo += space + "Rsp: 0x%016x" % ctx.Rsp
        self.rsp_address =ctx.Rsp
        bInfo += space + "Rbp: 0x%016x" % ctx.Rbp
        cInfo = "Rsi: 0x%016x" % ctx.Rsi
        cInfo += space + "Rdi: 0x%016x" % ctx.Rdi
        cInfo += space + "Rip: 0x%016x" % ctx.Rip
        self.rip_address = ctx.Rip
        dInfo = "R8: 0x%016x" % ctx.R8
        dInfo += space + "R9: 0x%016x" % ctx.R9
        dInfo += space + "R10: 0x%016x" % ctx.R10
        eInfo = "R11: 0x%016x" % ctx.R11
        eInfo += space + "R12: 0x%016x" % ctx.R12
        eInfo += space + "R13: 0x%016x" % ctx.R13
        fInfo = "R14: 0x%016x" % ctx.R14
        fInfo += space + "R15: 0x%016x" % ctx.R15
        printer.test(aInfo)
        printer.test(bInfo)
        printer.test(cInfo)
        printer.test(dInfo)
        printer.test(eInfo)
        printer.test(fInfo)
    def flags_register_info64(self,ctx):
        printer.info("标志位信息:")
        flags = ctx.EFlags
        if flags is None:
            printer.warn("标志寄存器为空")
        else:
            #i/o Ring0~3
            dEfl = 'iopl=%1d' % ((flags & 0x3000) >> 12)
            #OF
            if flags & 0x800:
                dEfl += ' ov' #溢出标志
            else:
                dEfl += ' no' #无溢出
            #DF
            if flags & 0x400:
                dEfl += ' dn' #向下
            else:
                dEfl += ' up' #向上
            #IF
            if flags & 0x200:
                dEfl += ' ei' #启用中断
            else:
                dEfl += ' di' #停用中断
            #SF
            if flags & 0x80:
                dEfl += ' ng' #正数
            else:
                dEfl += ' pl' #负数
            #ZF
            if flags & 0x40:
                dEfl += ' zr' #等于零
            else:
                dEfl += ' nz' #不等于零
            #AF
            if flags & 0x10:
                dEfl += ' ac' #有辅助进位
            else:
                dEfl += ' na' #无辅助进位
            #PF
            if flags & 0x4:
                dEfl += ' pe' #偶
            else:
                dEfl += ' po' #奇
            #CF
            if flags & 0x1:
                dEfl += ' cy' #有进位
            else:
                dEfl += ' nc' #无进位
            printer.test(dEfl)
    def segment_register_info64(self,ctx):
        printer.info("段寄存器信息:")
        space = "   "
        ainfo = "SegCs: 0x%016x" % ctx.SegCs
        ainfo += space + "SegSs: 0x%016x" % ctx.SegSs
        ainfo += space + "SegDs: 0x%016x" % ctx.SegDs
        binfo = "SegFs: 0x%016x" % ctx.SegFs
        binfo += space + "SegGs: 0x%016x" % ctx.SegGs
        binfo += space + "SegEs: 0x%016x" % ctx.SegEs
        printer.test(ainfo)
        printer.test(binfo)
    def eflags_register(self,ctx):
        printer.info("标志寄存器信息:")
        info = "EFlags: 0x%016x" % ctx.EFlags
        printer.test(info)
    def get_debug_event64(self):
        debug_event = wintype.DEBUG_EVENT()
        continue_status = wintype.DBG_CONTINUE
        if ctypes.windll.kernel32.WaitForDebugEvent(ctypes.byref(debug_event),wintype.INFINITE):
            self.h_thread = self.open_thread64(debug_event.dwThreadId)
            self.context = self.get_thread_context64(h_thread=self.h_thread)
            printer.info("调试代码: %d 线程ID: %d" % (debug_event.dwDebugEventCode, debug_event.dwThreadId))
            if debug_event.dwDebugEventCode ==wintype.EXCEPTION_DEBUG_EVENT:
                self.exception = debug_event.u.Exception.ExceptionRecord.ExceptionCode
                self.exception_address = debug_event.u.Exception.ExceptionRecord.ExceptionAddress
                printer.info("调试事件[EXCEPTION_DEBUG_EVENT]发生的内存地址: 0x%08x" % (self.exception_address))
                if self.exception == wintype.EXCEPTION_ACCESS_VIOLATION:
                    printer.info("触发调试的异常:EXCEPTION_ACCESS_VIOLATION[无效访问]")
                elif self.exception == wintype.EXCEPTION_BREAKPOINT:
                    printer.info("触发调试的异常:EXCEPTION_BREAKPOINT[断点]")
                    continue_status = self.debug_handler_breakpoint(64)
                elif self.exception == wintype.EXCEPTION_SINGLE_STEP:
                    printer.info("触发调试的异常:EXCEPTION_SINGLE_STEP[单步调试]")
                    continue_status = self.debug_single_step(64)
                elif self.exception == wintype.EXCEPTION_GUARD_PAGE:
                    printer.info("触发调试的异常:EXCEPTION_GUARD_PAGE[内存页访问]")
                elif self.exception == wintype.STATUS_WX86_BREAKPOINT:
                    printer.info("触发调试的异常:EXCEPTION_BREAKPOINT_WX86[断点]")
                    continue_status = self.debug_handler_breakpoint(64)
                elif self.exception == wintype.STATUS_WX86_SINGLE_STEP:
                    printer.info("触发调试的异常:STATUS_WX86_SINGLE_STEP[单步调试]")
                    continue_status = self.debug_single_step(64)
            if debug_event.dwDebugEventCode == wintype.EXIT_PROCESS_DEBUG_EVENT:
                if self.context:
                    printer.info("Rip: 0x%016x" % self.context.Rip)
                self.stop()
            ctypes.windll.kernel32.ContinueDebugEvent(debug_event.dwProcessId, debug_event.dwThreadId, continue_status)
        else:
            printer.warn("[*] get_debug_event64错误: %d" % ctypes.windll.kernel32.GetLastError())
    def run64(self):
        while self.debugger_active == True:
            if self.context:
                printer.info("Rip: 0x%016x" % self.context.Rip)
            self.get_debug_event64()
    def set_ep_address(self,path):
        pe = pefile.PE(path,fast_load=True)
        ep = pe.OPTIONAL_HEADER.AddressOfEntryPoint
        ep_address = ep + pe.OPTIONAL_HEADER.ImageBase
        self.ep_address = ep_address
    def set_software_breakpoint(self,address):
        printer.info("设置软件断点地址: 0x%08x" % address)
        if address not in self.breakpoints.keys():
            original_byte = self.read_process_memory(address,1)
            if original_byte != False:
                #\xCC 0xCC 中断指令INT 3,用于调试
                if self.write_process_memory(address,b"\xCC"):
                    self.breakpoints[address] = (address,original_byte)
                    return True
                else:
                    return False
            else:
                return False
    def func_address(self,dll,func):
        #handle = ctypes.windll.kernel32.GetModuleHandleA(dll)
        handle = ctypes.windll.kernel32.LoadLibraryA(dll)
        address = ctypes.windll.kernel32.GetProcAddress(handle, func)
        ctypes.windll.kernel32.CloseHandle(handle)
        return address
    def virtual_query(self,address):
        #print(hex(address))
        mbi = wintype.MEMORY_BASIC_INFORMATION()
        '''
        vq = ctypes.windll.kernel32.VirtualQueryEx(
            self.h_process,
            address, ctypes.byref(mbi), ctypes.sizeof(mbi)
        )
        '''
        vq = ctypes.windll.kernel32.VirtualQuery(address,ctypes.byref(mbi), ctypes.sizeof(mbi))
        
        if vq < ctypes.sizeof(mbi):
            printer.warn("virtual_query error!: %d" % ctypes.windll.kernel32.GetLastError())
            raise ValueError("virtual_query!")
        return mbi
    def virtual_protect(self,address,size,protect):
        old_protect = ctypes.c_ulong(0)
        if ctypes.windll.kernel32.VirtualProtectEx(
            self.h_process,
            address,size,protect,ctypes.byref(old_protect)):
            return old_protect.value
        return False
    def virtual_alloc(self,address,size,alloc_type,protect):
        alloc_addr = ctypes.windll.kernel32.VirtualAllocEx(
            self.h_process,
            address,size,alloc_type,protect
        )
        if alloc_addr:
            return alloc_addr
        return False
    def virtual_free(self,address,size,free_type):
        if ctypes.windll.kernel32.VirtualFreeEx(
            self.h_process,
            address,size,free_type):
            return True
        return False
    def stack_range(self,tHandle,fs=0x50):
        selector_entry = wintype.LDT_ENTRY()
        if ctypes.windll.kernel32.Wow64GetThreadSelectorEntry(
            tHandle,fs,ctypes.byref(selector_entry)):
            fs_base = selector_entry.BaseLow
            fs_base += (selector_entry.HighWord.Bits.BaseMid << 16) + (selector_entry.HighWord.Bits.BaseHi << 24)
            stack_top = self.read_process_memory(fs_base+4,4)
            stack_bottom = self.read_process_memory(fs_base + 8,4)
            stack_top = struct.unpack("<L",stack_top)[0]
            stack_bottom = struct.unpack("<L",stack_bottom)[0]
            return (stack_top,stack_bottom)
        return False
    def location_addr_stack(self,address,tHandle,fs=0x50):
        (stack_top,stack_bottom) = self.stack_range(tHandle,fs)
        if address >= stack_bottom and address <= stack_top:
            return True
        return False
    def interate_modules(self):
        mod_entry = wintype.MODULEENTRY32()
        snapshot = ctypes.windll.kernel32.CreateToolhelp32Snapshot(wintype.TH32CS_SNAPMODULE, self.pid)
        if snapshot == -1:
            printer.warn("interate_modules error!: %d" % ctypes.windll.kernel32.GetLastError())
            return False
        mod_entry.dwSize = ctypes.sizeof(mod_entry)
        if not ctypes.windll.kernel32.Module32First(snapshot, ctypes.byref(mod_entry)):
            printer.warn("interate_modules Module32First : %d" % ctypes.windll.kernel32.GetLastError())
            return False
        while True:
            yield mod_entry
            if not ctypes.windll.kernel32.Module32Next(snapshot, ctypes.byref(mod_entry)):
                break
        ctypes.windll.kernel32.CloseHandle(snapshot)
    def interate_modules_wchar(self):
        mod_entrys = []
        mod_entry = wintype.MODULEENTRY32W()
        snapshot = ctypes.windll.kernel32.CreateToolhelp32Snapshot(wintype.TH32CS_SNAPMODULE, self.pid)
        if snapshot == -1:
            printer.warn("interate_modules error_wchar!: %d" % ctypes.windll.kernel32.GetLastError())
            return False
        mod_entry.dwSize = ctypes.sizeof(mod_entry)
        if not ctypes.windll.kernel32.Module32FirstW(snapshot, ctypes.byref(mod_entry)):
            printer.warn("interate_modules_wchar Module32FirstW : %d" % ctypes.windll.kernel32.GetLastError())
            return False
        while True:
            #yield mod_entry
            mod_entrys.append(mod_entry)
            if not ctypes.windll.kernel32.Module32NextW(snapshot, ctypes.byref(mod_entry)):
                break
        ctypes.windll.kernel32.CloseHandle(snapshot)
        return mod_entrys
    def addr_in_module_wchar(self,address):
        loc = None
        for mod in self.interate_modules_wchar():
            if mod.modBaseAddr < address < mod.modBaseAddr + mod.modBaseSize:
                import copy
                loc = copy.copy(mod)
        return loc
    def read_process_memory(self,address,length):
        data = ""
        read_buf = ctypes.create_string_buffer(length)
        count = ctypes.c_ulong(0)
        ctypes.windll.kernel32.ReadProcessMemory(self.h_process,address,read_buf,length,ctypes.byref(count))
        data = read_buf.raw
        #print(count.value)
        return data
    def read_process_memory_ex(self,address,length):
        data = b""
        read_buf = ctypes.create_string_buffer(length)
        count = ctypes.c_ulong(0)
        ori_address = address
        ori_length = length
        try:
            old_protect = self.virtual_protect(ori_address,ori_length,wintype.PAGE_EXECUTE_READWRITE)
        except Exception as e:
            print('1:' + e)
        while length:
            #print(length)
            if not ctypes.windll.kernel32.ReadProcessMemory(self.h_process, address, read_buf, length, ctypes.byref(count)):
                if not len(data):
                    printer.warn("read_process_memory_ex: %d" % ctypes.windll.kernel32.GetLastError())
                    raise ValueError("read_process_memory_ex!")
                else:
                    return data
            data += read_buf.raw
            address += count.value
            length  -= count.value
        try:
            self.virtual_protect(ori_address,ori_length,old_protect)
        except Exception as e:
            print("2" + e)
        return data
    def read_string_memory(self,address,length):
        try:
            data = self.read_process_memory(address,length)
            pos_str = bytearray(data).find(b'\00')
            if pos_str !=-1:
                print(data[:pos_str])
                return data[:pos_str].decode()
        except Exception as e:
            print(e)
            return False
    def write_process_memory(self,address,data):
        count = ctypes.c_ulong(0)
        length = len(data)
        c_data = ctypes.c_char_p(data[count.value:])
        if not ctypes.windll.kernel32.WriteProcessMemory(self.h_process,address,c_data,length,ctypes.byref(count)):
            return False
        else:
            return True
    def decode_context(self,address,hex_dump=False):
        
        try:
            mbi = self.virtual_query(address)
        except Exception as e:
            pass
            #return "[内存页权限!]"
        
        #if not mbi.Protect & wintype.PAGE_READWRITE:
            #return "[内存不可读!]"
        #if mbi.BaseAddress == self.peb or mbi.BaseAddress in self.tebs.values():
        if address == self.peb or address in self.tebs.values():
            return "[内存地址位于TEB或PEB范围内!]"
        try:
            string_buf_size = 256
            explored = self.read_process_memory_ex(address,string_buf_size)
        except Exception as e:
            return "[读取内存数据(字符串)失败!]"
        if self.location_addr_stack(address,self.h_thread,fs=0x50):
            location = "[地址位于Stack(栈)内!]"
        else:
            module = self.addr_in_module_wchar(address)
            if module:
                location = "[.data(数据节): %s]" % module.szModule
            else:
                location = "[地址可能位于堆上!]"
        explored_str = self.get_ascii_string(explored)
        if not explored_str:
            explored_str = self.get_unicode_string(explored)
        if not explored_str and hex_dump:
            explored_str = self.hex_dump(explored)
        if not explored_str:
            explored_str = self.get_printable_string(explored)
        if hex_dump:
            return "%s --> %s" % (explored_str, location)
        else:
            return "%s (%s)" % (explored_str, location)
    def stack_dump_context(self, context=None, stack_depth=5, print_dots=True, hex_dump=False):
        stack_list = {}
        stack_context = ""
        if context:
            for offset in range(0,stack_depth + 1):
                try:
                    value = self.read_process_memory_ex(context.Rsp + offset * 4,4)
                    rsp = struct.unpack("<L",value)[0]
                    stack_list["rsp+%02x"%(offset*4)] = {}
                    stack_list["rsp+%02x"%(offset*4)]['value'] = rsp
                    stack_list["rsp+%02x"%(offset*4)]['desc'] = self.decode_context(rsp,hex_dump)
                except Exception as e:
                    #print('stack_dump_context:%s'% e)
                    stack_list["rsp+%02x"%(offset*4)] = {}
                    stack_list["rsp+%02x"%(offset*4)]['value'] = 0
                    stack_list["rsp+%02x"%(offset*4)]['desc'] = "[数据无效!]"
        for offset in range(0, stack_depth + 1):
            stack_context += "  +%02x: 0x%08x (%08d) -> %s\n" %    \
            (                                                   \
                offset * 4,                                     \
                stack_list["rsp+%02x"%(offset*4)]["value"],   \
                stack_list["rsp+%02x"%(offset*4)]["value"],   \
                stack_list["rsp+%02x"%(offset*4)]["desc"]     \
            )
        return stack_context
    def dump_ip(self,context=None,hex_dump=False):
        try:
            address = context.Rip
            data = self.read_process_memory_ex(address,8)
        except Exception as e:
            printer.warn("[func]dump_ip")
            return False
        printer.warn("<----------------------------------",flag="")
        for i in self.disam_code(data,address):
            printer.test("Rip %s" %(i))
        printer.warn("----------------------------------->",flag="")
    def dump_ax(self,context=None,hex_dump=False):
        data = self.decode_context(context.Rax)
        printer.warn("<----------------------------------",flag="")
        printer.test("RAX: 0x%08x (%10d) -> %s" % (context.Rax,context.Rax,data))
        printer.warn("<----------------------------------",flag="")
    def dump_bx(self,context=None,hex_dump=False):
        data = self.decode_context(context.Rbx)
        printer.warn("<----------------------------------",flag="")
        printer.test("RBX: 0x%08x (%10d) -> %s" % (context.Rbx,context.Rbx,data))
        printer.warn("<----------------------------------",flag="")
    def dump_cx(self,context=None,hex_dump=False):
        data = self.decode_context(context.Rcx)
        printer.warn("<----------------------------------",flag="")
        printer.test("RCX: 0x%08x (%10d) -> %s" % (context.Rcx,context.Rcx,data))
        printer.warn("<----------------------------------",flag="")
    def dump_dx(self,context=None,hex_dump=False):
        data = self.decode_context(context.Rdx)
        printer.warn("<----------------------------------",flag="")
        printer.test("RDX: 0x%08x (%10d) -> %s" % (context.Rdx,context.Rdx,data))
        printer.warn("<----------------------------------",flag="")
    def dump_di(self,context=None,hex_dump=False):
        data = self.decode_context(context.Rdi)
        printer.warn("<----------------------------------",flag="")
        printer.test("RDI: 0x%08x (%10d) -> %s" % (context.Rdi,context.Rdi,data))
        printer.warn("<----------------------------------",flag="")
    def dump_si(self,context=None,hex_dump=False):
        data = self.decode_context(context.Rsi)
        printer.warn("<----------------------------------",flag="")
        printer.test("RSI: 0x%08x (%10d) -> %s" % (context.Rsi,context.Rsi,data))
        printer.warn("<----------------------------------",flag="")
    def dump_bp(self,context=None,hex_dump=False):
        data = self.decode_context(context.Rbp)
        printer.warn("<----------------------------------",flag="")
        printer.test("RBP: 0x%08x (%10d) -> %s" % (context.Rbp,context.Rbp,data))
        printer.warn("<----------------------------------",flag="")
    def dump_sp(self,context=None,hex_dump=False):
        data = self.decode_context(context.Rsp)
        printer.warn("<----------------------------------",flag="")
        printer.test("RSP: 0x%08x (%10d) -> %s" % (context.Rsp,context.Rsp,data))
        printer.warn("<----------------------------------",flag="")
    def disam_code(self,data,address):
        disasm = Cs(CS_ARCH_X86, CS_MODE_32)
        mnemonic = opStr = addr = ""
        result = ""
        for i in disasm.disasm(data,address):
            addr = i.address
            mnemonic = i.mnemonic
            opStr = i.op_str
            result = hex(addr) + " --> " + mnemonic + " " + opStr
            yield result
    def get_ascii_string(self,data):
        a_str = ""
        for c in data:
            #if ord(c) < 32 or ord(c) > 126:
            if c<32 or c>126:
                break
            a_str += chr(c)
        if len(a_str) < 2:
            return False
        return a_str
    def get_unicode_string(self,data):
        u_str = ""
        other = True
        for c in data:
            if other == True:
                #if ord(c)<32 or ord(c) > 126:
                if c<32 or c>126:
                    break
                u_str += chr(c)
            other = not other
        if len(u_str) < 2:
            return False
        return u_str
    def get_printable_string(self,data):
        pstr = ""
        for c in data:
            if c>=32 and c <=126:
                pstr += chr(c)
                pstr += "."
        return pstr

    def hex_dump(self,data, addr=0, prefix=""):
        dump  = prefix
        slice = ""
        for byte in data:
            if addr % 16 == 0:
                dump += " "
                for char in slice:
                    if ord(char) >= 32 and ord(char) <= 126:
                        dump += char
                    else:
                        dump += "."
                dump += "\n%s%04x: " % (prefix, addr)
                slice = ""
            dump  += "%02x " % ord(byte)
            slice += byte
            addr  += 1
        remainder = addr % 16
        if remainder != 0:
            dump += "   " * (16 - remainder) + " "
        for char in slice:
            if ord(char) >= 32 and ord(char) <= 126:
                dump += char
            else:
                dump += "."
        return dump + "\n"
    def stop(self):
        if ctypes.windll.kernel32.DebugActiveProcessStop(self.pid):
            self.debugger_active = False
            ctypes.windll.kernel32.CloseHandle(self.process_information.hThread)
            ctypes.windll.kernel32.CloseHandle(self.process_information.hProcess)
            printer.warn("动态调试结束...")
        else:
            printer.warn("stop错误: %d" % ctypes.windll.kernel32.GetLastError())
    def debug_handler_breakpoint(self,flag):
        fpath = os.path.join(settings.LIB_HANDLE_PATH,self.hmodule['bp'])
        with open(fpath,"r",encoding="utf-8") as f:
            mod = loader.load_module(f.read())
            #mod = loader.
            continue_status = mod.run(self,flag)
        print(hex(continue_status))
        return continue_status
    def debug_single_step(self,flag):
        fpath = os.path.join(settings.LIB_HANDLE_PATH,self.hmodule['st'])
        with open(fpath,"r",encoding="utf-8") as f:
            mod = loader.load_module(f.read())
            continue_status = mod.run(self,flag)
        return continue_status